﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace AirLib
{
    public class Slideshow
    {
        #region Fields

        private Guid _sessionGuid = Guid.NewGuid();
        private List<string> _photoList = new List<string>();
        private string _appleTvIpAddress;
        private int _currentPhoto = 0;
        
        #endregion Fields
        

        #region Properties

        /// <summary>
        /// Gets the photo list.
        /// </summary>
        /// <value>
        /// The photo list.
        /// </value>
        public List<string> PhotoList
        {
            get { return _photoList; }
        }

        #endregion Properties

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="Slideshow"/> class.
        /// </summary>
        public Slideshow(string ipAddress, int streamHostPort)
        {
            _appleTvIpAddress = ipAddress;

            ReverseConnectionHandler eventHandler = new ReverseConnectionHandler(ipAddress, "event", _sessionGuid);
            eventHandler.EventRaised += new ReverseConnectionHandler.EventFiredDelegate(EventHandler_EventRaised);

            ReverseConnectionHandler photoEventHandler = new ReverseConnectionHandler(ipAddress, "photo", _sessionGuid);
            eventHandler.EventRaised += new ReverseConnectionHandler.EventFiredDelegate(PhotoEventHandler_EventRaised);

            ReverseConnectionHandler photoConnectionHandler = new ReverseConnectionHandler(_appleTvIpAddress, "slideshow", _sessionGuid);
            photoConnectionHandler.EventRaised += new ReverseConnectionHandler.EventFiredDelegate(ReverseConnectionHandler_EventRaised);

            
        }

        /// <summary>
        /// Event raised.
        /// </summary>
        /// <param name="eventMessage">The event message.</param>
        /// <returns></returns>
        byte[] EventHandler_EventRaised(string eventMessage)
        {
            Debug.WriteLine(eventMessage);
            return null;
        }

        /// <summary>
        /// Event raised.
        /// </summary>
        /// <param name="eventMessage">The event message.</param>
        /// <returns></returns>
        byte[] PhotoEventHandler_EventRaised(string eventMessage)
        {
            Debug.WriteLine(eventMessage);
            return null;
        }

        /// <summary>
        /// Reverses the connection handler_ event raised.
        /// </summary>
        /// <param name="eventMessage">The event message.</param>
        /// <returns>Response</returns>
        byte[] ReverseConnectionHandler_EventRaised(string eventMessage)
        {
            if(eventMessage.Contains("GET /slideshows/1/assets/1"))
            {            
                string body = Properties.Resources.SlideshowResponsePlist;
                string image = Convert.ToBase64String(File.ReadAllBytes(_photoList[_currentPhoto]));
                int photoNumber = _currentPhoto + 1;
                body = body.Replace("{1}", photoNumber.ToString());                
                body = body.Replace("{0}", image);
                byte[] bodyData = System.Text.Encoding.ASCII.GetBytes(body);

                string response = "HTTP/1.1 200 OK\n" +
                                "Content-Type: application/x-apple-binary-plist\n" +
                                "Content-Length: " + bodyData.Length + "\n\n";

               byte[] byData = System.Text.Encoding.ASCII.GetBytes(response + body);
               _currentPhoto++;

               return byData;
            }
            else
            {
                return null;
            }

        }

        #endregion Constructor

        #region Methods

      

        public void Start()
        {

            int length = Encoding.ASCII.GetBytes(Properties.Resources.SlideshowPutPlist).Length;

            string request = "PUT /slideshows/1 HTTP/1.1\n" +
            "Content-Type: text/x-apple-plist+xml\n" +
            "Content-Length: " + length + "\n" +
            "User-Agent: MediaControl/1.0\n" +
            "X-Apple-Session-ID: " + _sessionGuid.ToString() + "\n\n";
            request += Properties.Resources.SlideshowPutPlist + "\n\n";               


            using (TcpClient tcpClient = new TcpClient(_appleTvIpAddress, AppleTv.AppleTvPort))
            {

                byte[] byData = System.Text.Encoding.ASCII.GetBytes(request);

                //get the client stream to read data from.
                NetworkStream clientStream = tcpClient.GetStream();

                SendMessage(clientStream, request);                                

                byte[] buffer = new byte[10000];

                int recieved = clientStream.Read(buffer, 0, buffer.Length);
                string str = Encoding.ASCII.GetString(buffer, 0, recieved);

               

                //Now start doing a "keepalive"
                //while (true)
                //{
                //    //Simply send the characters "ok" every two seconds
                //    //Todo: Determine what the actual message that apple products send
                //    //SendMessage(clientStream, "ok");
                //    Thread.Sleep(1000);
                //}
                                
            }
        }

        /// <summary>
        /// Sends a message across the NetworkStream
        /// </summary>
        /// <param name="clientStream">The stream to send the message down</param>
        /// <param name="message">The message to send</param>
        public void SendMessage(NetworkStream clientStream, string message)
        {
            byte[] buffer = new ASCIIEncoding().GetBytes(message);
            try
            {
                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
            }
            catch (System.IO.IOException e)
            {
                Debug.WriteLine("IOException: " + e.Message);
            }
        }

        #endregion Methods


    }
}
